using System;
using System.CodeDom;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
using System.Windows.Forms;
using System.Xml;
using System.Xml.Schema;
using System.Xml.Serialization;
using Microsoft.CSharp;
using OpenComposite.Base.Designer;
using OpenComposite.EII.BRules;
using OpenComposite.EII.Designer.Generic;
using OpenComposite.Repository.Properties;
using OpenComposite.EII.Repository;

namespace OpenComposite.EII.Designer.BRules
{
	public class BusinessRuleSymbol : Symbol, IRepositoryItemSymbol
	{
		#region Initialization
		public BusinessRuleSymbol()
		{
			init();
		}
		private void init()
		{
			this.BeginUpdate();

			//this.Name = "businessRuleSymbol" + GetCount(typeof(BusinessRuleSymbol));
			this.Text = "Business Rule";

			this.NameTextBox.AutoSize = false;
			this.NameTextBox.TextChanged += new EventHandler(NameTextBox_TextChanged);

			this.Size = new Size(450, 200);
			this.MinimumSize = new Size(250, 200);

			this.Border = BorderType.RoundedRectangle;
			this.BorderColor = Color.Navy;
			this.BorderWidth = 4;

			this.ContextMenuStrip.Items.Clear();
			this.ContextMenuStrip.Items.Add(new System.Windows.Forms.ToolStripMenuItem(
				"Show C# Code", Resources.csharp_png, new EventHandler(Context_ShowCSCode)));
			this.ContextMenuStrip.Items.Add(new System.Windows.Forms.ToolStripSeparator());
			this.ContextMenuStrip.Items.Add(new System.Windows.Forms.ToolStripMenuItem(
				"Delete Business Rule", Resources.delete, new EventHandler(Context_Delete)));

			_brule = null;
			_imgUser = null;

			this.EndUpdate();
		}

		void NameTextBox_TextChanged(object sender, EventArgs e)
		{

			if ( this.DesignerViewControl != null ) {
				refreshRuleReferences();
			}
		}
		#endregion

		#region Public Members

		#region Properties

		public THENELSESymbol ThenElse
		{
			get { return _thenelseSymbol; }
		}
		public List<IFSymbol> IfList
		{
			get { return _ifSymbols; }
		}
		public List<THENResultSymbol> ThenList
		{
			get { return _thenSymbols; }
		}
		public ELSEResultSymbol Else
		{
			get { return _elseSymbol; }
		}
		public ONERRORResultSymbol OnError
		{
			get { return _onerrorSymbol; }
		}
		public RepositoryBusinessRule RepositoryRule
		{
			get { return this.RepositoryItem as RepositoryBusinessRule; }
		}

		public bool IsParticipantRule
		{
			get { return _isParticipantRule; }
		}
		#endregion

		#region Override

		#region Properties
		public override bool CanFocused
		{
			get
			{
				return true;
			}
		}
		public override bool CanMove
		{
			get
			{
				return true;
			}
		}
		public override bool CanResize
		{
			get
			{
				return true;
			}
		}
		public override bool CanSelect
		{
			get
			{
				return true;
			}
		}
		public override bool IsContainer
		{
			get
			{
				return true;
			}
		}
		public override bool NoClip
		{
			get
			{
				return false;
			}
		}

		private void refreshRuleReferences()
		{
			if ( this.DesignerViewControl == null ) return;
			if ( this.RepositoryItem == null ) return;
			try {
				this.RepositoryRule.Name = this.NameTextBox.Text;
				this.RepositoryRule.Save();
				foreach ( DesignerControl ctrl in this.DesignerViewControl.DesignerControls ) {
					BusinessRuleSymbol rule = ctrl as BusinessRuleSymbol;
					if ( rule == null ) continue;
					foreach ( IFSymbol condition in rule.IfList ) {
						if ( condition.IFCondition.LeftRuleID == this.RepositoryItem.ID ) {
							condition.IFCondition.LeftValueString = this.NameTextBox.Text;
							condition.RefreshConditions();
						} else if ( condition.IFCondition.RightRuleID == this.RepositoryItem.ID ) {
							condition.IFCondition.RightValueString = this.NameTextBox.Text;
							condition.Invalidate();
							condition.Refresh();
							condition.RefreshConditions();
						}
					}
				}
			} catch ( Exception ) {
			}
		}
		#endregion

		#region Drag & Drop
		public override object GetDragObject(Point location, System.Windows.Forms.MouseButtons button)
		{
			return null;
		}
		public override bool IsDropAllowed(object obj, Point location, System.Windows.Forms.MouseButtons button)
		{
			if ( obj == null )
				return false;
			else
				return IsDropAllowed(obj.GetType(), location, button);
		}
		public override bool IsDropAllowed(Type type, Point location, MouseButtons button)
		{
			return ( type == typeof(IFSymbol) ||
					 type == typeof(ANDSymbol) ||
					 type == typeof(ORSymbol) ||
					 type == typeof(THENResultSymbol) ||
					 type == typeof(OpenComposite.EII.Designer.BRules.ParticipantRules.THENParticipantSymbol) ) &&
					button == System.Windows.Forms.MouseButtons.Left;
		}
		public override void DropObject(object obj, Point location, System.Windows.Forms.MouseButtons button)
		{
			if ( IsDropAllowed(obj, location, button) && button == System.Windows.Forms.MouseButtons.Left ) {
				DesignerControl dc = obj as DesignerControl;
				if ( dc is IFSymbol ) {
					int y = ( _ifSymbols.Count == 0 ? _yTop : _ifSymbols[_ifSymbols.Count - 1].Bottom + _padIFs );
					( (IFSymbol)dc ).Location = new Point(0, y);
					_ifSymbols.Add((IFSymbol)dc);
					dc.SizeChanged += new EventHandler(ifsymbol_SizeChanged);
					resizeBRuleSymbol();
				} else if ( dc is THENResultSymbol ) {
					Rectangle rclient = this.CalculateClientArea();
					int x = rclient.Width - dc.Width;
					int y = ( _thenSymbols.Count == 0 ? _yTop : _thenSymbols[_thenSymbols.Count - 1].Bottom + _padIFs );
					( (THENResultSymbol)dc ).Location = new Point(x, y);
					_thenSymbols.Add((THENResultSymbol)dc);
					dc.SizeChanged += new EventHandler(thenelsesymbol_SizeChanged);
					reposTHENELSESymbols();
					resizeBRuleSymbol();
				} else {
					dc.Location = this.PointToDesignerControlClient(location);
				}
				this.Controls.Add(dc);
			}
		}
		#endregion

		#region Paint
		public override void PaintBackground(System.Windows.Forms.PaintEventArgs pe)
		{
			base.PaintBackground(pe);
		}
		public override void Paint(System.Windows.Forms.PaintEventArgs pe)
		{
			base.Paint(pe);
			if ( _isParticipantRule ) {
				Rectangle rc = this.GetPaintClientArea();
				pe.Graphics.DrawImageUnscaled(_imgUser, rc.Location);
			}
		}
		#endregion

		public override object GetService(Type serviceType)
		{
			if ( _brule != null )
				return _brule.GetService(serviceType);
			else
				return base.GetService(serviceType);
		}
		#endregion

		#region Methods
		public void RefreshSymbols()
		{
			this.BeginUpdate();
			reposIFSymbols();
			reposTHENELSESymbols();
			resizeBRuleSymbol();
			this.EndUpdate();
		}
		#endregion

		#endregion

		#region Internal Members
		#region Methods
		internal void ResizeThenElseErrors()
		{
			Graphics g = Graphics.FromHwnd(this.DesignerViewControl.Handle);
			if ( g == null ) return;

			int width = 0;
			foreach ( DesignerControl ctrl in this.Controls ) {
				ActionSymbol action = ctrl as ActionSymbol;
				if ( action != null ) {
					SizeF size = g.MeasureString(action.TextBox.Text, action.TextBox.Font, new SizeF(0, action.TextBox.Height),
						new StringFormat(
							StringFormatFlags.DirectionRightToLeft |
							StringFormatFlags.FitBlackBox |
							StringFormatFlags.LineLimit));
					Size old = action.Size;
					old = old - action.TextBox.Size;
					old = old + Size.Ceiling(size);
					if ( old.Width > width ) {
						width = (int)old.Width;
					}
				}
			}
			foreach ( DesignerControl ctrl in this.Controls ) {
				ActionSymbol action = ctrl as ActionSymbol;
				if ( action != null ) {
					action.Size = new Size(width, 50);
				}
			}
		}
		#endregion
		#endregion

		#region Protected Members

		#region Override
		protected override void OnTextChanged(EventArgs e)
		{
			this.Name = RepositoryService.GetIdentifier(this.Text);
			#region Obsolete
			//if ( _brule != null ) {
			//    string brname = this.Name;
			//    bool end = false;
			//    DataRow row;
			//    int i = 0;
			//    do {
			//        row = Global.BusinessRuleData.GetBusinessRuleDataRow(
			//            Global.CurrentUser.OrganizationID, brname);
			//        if ( row != null && ( _brule == null || row["name"].ToString() != _brule.BusinessRuleName ) ) {
			//            //System.Windows.Forms.MessageBox.Show(
			//            //    "A business rule with this name exists." + Environment.NewLine +
			//            //    "Please choose an other name.", "Business Rule",
			//            //    System.Windows.Forms.MessageBoxButtons.OK,
			//            //    System.Windows.Forms.MessageBoxIcon.Information);
			//            //this.NameTextBox.Edit();
			//            //return;
			//            brname = this.Name + i.ToString();
			//            i++;
			//        } else {
			//            end = true;
			//        }
			//    } while ( !end );
			//    if ( this._brule != null ) {
			//        if ( _brule.Name != brname ) {
			//            Global.BusinessRuleData.RenameRule(_brule.BusinessRuleName, brname, brname, Global.CurrentUser.OrganizationID);
			//        }
			//        this._brule.Name = this.Text;
			//    }
			//}
			#endregion
			base.OnTextChanged(e);
		}
		protected override void OnControlRemoved(DesignerControl ctrl)
		{
			if ( ctrl is IFSymbol ) {
				_ifSymbols.Remove((IFSymbol)ctrl);
				ctrl.SizeChanged -= new EventHandler(ifsymbol_SizeChanged);
				reposIFSymbols();
			}
			base.OnControlRemoved(ctrl);
		}
		protected override void OnRemoving(System.ComponentModel.CancelEventArgs e)
		{
			if ( _isInRepositoryDelete ) {
				e.Cancel = false;
			} else {
				e.Cancel = true;
				if ( _brule != null ) {
					if ( _brule.Delete(true) ) {
						e.Cancel = false;
					}
				}
			}
			base.OnRemoving(e);
		}
		#endregion

		#endregion

		#region Private Members

		#region Variables
		private int _yTop = 20;
		private int _padIFs = 5;
		private THENELSESymbol _thenelseSymbol;
		private List<IFSymbol> _ifSymbols;
		private List<THENResultSymbol> _thenSymbols;
		private ELSEResultSymbol _elseSymbol;
		private ONERRORResultSymbol _onerrorSymbol;
		private Image _imgUser;

		private bool _isParticipantRule = false;
		private bool _isReadXML = false;
		/// <summary>
		/// Used by move & copy rules from repository tree to rule designer
		/// </summary>
		private bool _allowReadingRoutes = false;
		private volatile bool _isInRepositoryDelete = false;
		#endregion

		#region Methods

		private void initIFTHENELSESymbols()
		{
			if ( _isReadXML )	// do not initialize if loading from xml
				return;

			this.BeginUpdate();
			Rectangle rclient = this.CalculateClientArea();
			//
			// _thenelseSymbol
			//
			_thenelseSymbol = null;
			//_thenelseSymbol = new THENELSESymbol();
			//_thenelseSymbol.Bounds = new Rectangle(rclient.Width - _thenelseSymbol.Width, _yTop,
			//                                       _thenelseSymbol.Width, rclient.Height - _yTop - 1);
			//_thenelseSymbol.Anchor = System.Windows.Forms.AnchorStyles.Top |
			//                         System.Windows.Forms.AnchorStyles.Right |
			//                         System.Windows.Forms.AnchorStyles.Bottom;

			// _thenSymbols
			_thenSymbols = new List<THENResultSymbol>();
			THENResultSymbol thenSymbol;
			if ( _isParticipantRule ) {
				thenSymbol = new ParticipantRules.THENParticipantSymbol();
			} else {
				thenSymbol = new THENResultSymbol();
			}
			thenSymbol.Location = new Point(rclient.Width - thenSymbol.Width, _yTop);
			thenSymbol.Anchor = AnchorStyles.Top | AnchorStyles.Right;
			thenSymbol.SizeChanged += new EventHandler(this.thenelsesymbol_SizeChanged);
			_thenSymbols.Add(thenSymbol);



			// _elseSymbol
			if ( _isParticipantRule ) {
				_elseSymbol = new ParticipantRules.ELSEParticipantSymbol();
			} else {
				_elseSymbol = new ELSEResultSymbol();
			}
			_elseSymbol.Location = new Point(rclient.Width - thenSymbol.Width,
											 _thenSymbols[_thenSymbols.Count - 1].Bottom + 5);
			_elseSymbol.Anchor = AnchorStyles.Top | AnchorStyles.Right;
			_elseSymbol.SizeChanged += new EventHandler(this.thenelsesymbol_SizeChanged);

			// _onerrorSymbol
			if ( _isParticipantRule ) {
				_onerrorSymbol = new ParticipantRules.ONERRORParticipantSymbol();
			} else {
				_onerrorSymbol = new ONERRORResultSymbol();
			}
			_onerrorSymbol.Location = new Point(rclient.Width - thenSymbol.Width, _elseSymbol.Bottom + 5);
			_onerrorSymbol.Anchor = AnchorStyles.Top | AnchorStyles.Right;
			_onerrorSymbol.SizeChanged += new EventHandler(this.thenelsesymbol_SizeChanged);

			//
			// _ifSymbols
			//
			_ifSymbols = new List<IFSymbol>();

			// create first IFSymbol
			IFSymbol ifSymbol = new IFSymbol();
			ifSymbol.Location = new Point(0, _yTop);
			_ifSymbols.Add(ifSymbol);
			ifSymbol.SizeChanged += new EventHandler(ifsymbol_SizeChanged);

			//this.Controls.Add(_thenelseSymbol);
			this.Controls.Add(thenSymbol);
			this.Controls.Add(ifSymbol);
			this.Controls.Add(_elseSymbol);
			this.Controls.Add(_onerrorSymbol);
			this.EndUpdate();
		}

		private void reposIFSymbols()
		{
			this.BeginUpdate();
			Rectangle rclient = this.CalculateClientArea();
			for ( int i = 0; i < _ifSymbols.Count; i++ ) {
				if ( !_ifSymbols[i].Visible ) {
					_ifSymbols.RemoveAt(i);
				} else {
					int y = ( i == 0 ? _yTop : _ifSymbols[i - 1].Bottom + _padIFs );
					_ifSymbols[i].Location = new Point(0, y);
				}
			}
			this.EndUpdate();
		}
		private void reposTHENELSESymbols()
		{
			this.BeginUpdate();
			Rectangle rclient = this.CalculateClientArea();
			for ( int i = 0; i < _thenSymbols.Count; i++ ) {
				if ( !_thenSymbols[i].Visible ) {
					_thenSymbols.RemoveAt(i);
				} else {
					int x = rclient.Width - _thenSymbols[i].Width;
					int y = ( i == 0 ? _yTop : _thenSymbols[i - 1].Bottom + _padIFs );
					_thenSymbols[i].Location = new Point(x, y);
				}
			}
			int xElse = rclient.Width - _elseSymbol.Width;
			int yElse = ( _thenSymbols.Count == 0 ? _yTop : _thenSymbols[_thenSymbols.Count - 1].Bottom + _padIFs );
			_elseSymbol.Location = new Point(xElse, yElse);

			int xError = rclient.Width - _onerrorSymbol.Width;
			int yError = _elseSymbol.Bottom + _padIFs;
			_onerrorSymbol.Location = new Point(xError, yError);

			this.EndUpdate();
		}
		private void resizeBRuleSymbol()
		{
			Rectangle rclient = this.CalculateClientArea();
			if ( _ifSymbols[_ifSymbols.Count - 1].Bottom > _onerrorSymbol.Bottom ) {
				int height = this.Height + ( _ifSymbols[_ifSymbols.Count - 1].Bottom - rclient.Height ) + 10;
				this.MinimumSize = new Size(this.MinimumSize.Width, height);
				this.Height = height;
			} else {
				int height = this.Height + ( _onerrorSymbol.Bottom - rclient.Height ) + 10;
				this.MinimumSize = new Size(this.MinimumSize.Width, height);
				this.Height = height;
			}
		}
		#endregion

		#region Event Handler
		private void Context_ShowCSCode(object sender, EventArgs e)
		{
			System.Windows.Forms.Application.DoEvents();
			//List<string> vocab;
			//List<string> rules;
			//codeView.Code = BusinessRulesCodeGenerator.GenerateBusinessRuleCode(this, out vocab, out rules);
			Dictionary<string, string> parameters;
			List<string> results;
			List<int> usedbrules;
			List<int> ruleConstIDs;
			string code = "";
			try {
				code = BusinessRulesCodeGenerator.GenerateOrchestrationRuleCode(this,
					out parameters, out results, out usedbrules, out ruleConstIDs);
			} catch ( Exception ex ) {
				MessageBox.Show(ex.Message, this.Text, MessageBoxButtons.OK, MessageBoxIcon.Error);
				return;
			}
			FormCodeViewer codeView = new FormCodeViewer();
			codeView.Code = code;
			codeView.ShowDialog();
			System.Windows.Forms.Application.DoEvents();
		}
		private void Context_Delete(object sender, EventArgs e)
		{
			System.Windows.Forms.Application.DoEvents();
			this.Delete(true);

		}
		private void ifsymbol_SizeChanged(object sender, EventArgs e)
		{
			reposIFSymbols();
		}
		private void thenelsesymbol_SizeChanged(object sender, EventArgs e)
		{
			reposTHENELSESymbols();
			resizeBRuleSymbol();
		}
		#endregion

		#endregion

		#region IXmlSerializable Members

		public bool AllowReadingRoutes
		{
			get { return _allowReadingRoutes; }
			set { _allowReadingRoutes = value; }
		}

		public void SaveToXmlDiagram()
		{
			XmlDocument xd = new XmlDocument();
			XmlNode xnDiagram = xd.AppendChild(xd.CreateElement("DesignerDiagram"));
			XmlNode xnRule = xd.DocumentElement.AppendChild(xd.CreateElement("BusinessRule"));

			XmlSerializer xs = new XmlSerializer(typeof(BusinessRuleSymbol));
			XmlWriterSettings settings = new XmlWriterSettings();
			settings.Indent = false;
			settings.NewLineChars = string.Empty;
			settings.OmitXmlDeclaration = true;

			using ( StringWriter sw = new StringWriter() )
			using ( XmlWriter xw = XmlWriter.Create(sw, settings) ) {
				xs.Serialize(xw, this);
				xw.Flush();
				XmlDocument x = new XmlDocument();
				x.LoadXml(sw.ToString());
				xnRule.AppendChild(xd.ImportNode(x.DocumentElement, true));
			}
			this.RepositoryRule.Diagram = xd;
		}

		public override void ReadXml(XmlReader reader)
		{
			RepositoryService repSvc = (RepositoryService)this.GetService(typeof(RepositoryService));
			if ( repSvc == null && !_allowReadingRoutes )
				throw new NullReferenceException("RepositoryService not available.");

			_isReadXML = true;
			try {
				System.ComponentModel.BooleanConverter bc = new System.ComponentModel.BooleanConverter();
				//taken out for move&copy from repo tree to designer
				//#region Remove Child IF/THEN/ELSE/ONERROR/AND/OR-Symbols
				//List<DesignerControl> remove = new List<DesignerControl>();
				//foreach ( DesignerControl dc in this.Controls ) {
				//    if ( dc is IFSymbol || dc is THENELSESymbol || dc is ANDSymbol || dc is ORSymbol ||
				//         dc is THENResultSymbol || dc is ELSEResultSymbol || dc is ONERRORResultSymbol )
				//        remove.Add(dc);
				//}
				//foreach ( DesignerControl dc in remove ) {
				//    this.Controls.Remove(dc);
				//    dispose(dc);
				//}
				//remove.Clear();
				//remove = null;
				//#endregion

				if ( _ifSymbols == null )
					_ifSymbols = new List<IFSymbol>();
				else
					_ifSymbols.Clear();
				if ( _thenSymbols == null )
					_thenSymbols = new List<THENResultSymbol>();
				else
					_thenSymbols.Clear();
				dispose(_thenelseSymbol);
				dispose(_elseSymbol);
				dispose(_onerrorSymbol);

				// used by: move & copy rules from repo tree to designer
				if ( _allowReadingRoutes ) this.BeginUpdate();

				while ( reader.Read() ) {
					switch ( reader.Name ) {
						case "DesignerControl":
							if ( reader.NodeType == XmlNodeType.EndElement )
								return;
							break;
						case "IF":
							readIF(reader);
							break;
						case "THENELSE":
							readTHENELSE(reader);
							break;
						case "THEN":
							readTHEN(reader);
							break;
						case "ELSE":
							readELSE(reader);
							break;
						case "ONERROR":
							readONERROR(reader);
							break;
						case "DesignerControls":
							ReadChildControls(reader);
							break;
						case "RepositoryBusinessRule":
							if ( reader.MoveToAttribute("id") && reader.ReadAttributeValue() )
								//if ( !_allowReadingRoutes ) {
								this.RepositoryItem = repSvc.GetItem(ItemType.BRule, int.Parse(reader.Value), false);
							//}
							if ( reader.MoveToAttribute("isMainControl") && reader.ReadAttributeValue() )
								if ( reader.Value == true.ToString() )
									this.DesignerViewControl.MainControl = this;
							if ( reader.MoveToAttribute("isRef") && reader.ReadAttributeValue() )
								this.IsReference = (bool)bc.ConvertFromString(reader.Value);
							break;
						default:
							ReadStandardProperties(reader);
							break;
					}
				}
			} finally {
				_isReadXML = false;
				if ( _allowReadingRoutes ) this.EndUpdate();
			}
		}

		protected override void ReadChildControls(XmlReader reader)
		{
			while ( reader.Read() ) {
				switch ( reader.Name ) {
					case "Route":
						if ( _allowReadingRoutes ) {
							if ( reader.NodeType == XmlNodeType.Element ) {
								string typename = reader.GetAttribute("Type");
								try {
									DesignerControl dc = AddSerializedDesignerControl(typename, reader, false);
									//this.DesignerViewControl.DesignerControls.Add(dc);
								} catch { }
							}
						}
						break;
					case "Routes":
						if ( reader.NodeType == XmlNodeType.EndElement )
							return;
						break;
					case "DesignerControl":
						if ( reader.NodeType == XmlNodeType.Element ) {
							string typename = reader.GetAttribute("Type");
							DesignerControl dc = AddSerializedDesignerControl(typename, reader);
						}
						break;
					default:
						base.ReadChildControls(reader);
						break;
				}
			}
		}
		private void ReadRoutes(XmlReader reader)
		{
		}
		private void readIF(XmlReader reader)
		{
			while ( reader.Read() ) {
				switch ( reader.Name ) {
					case "IF":
						if ( reader.NodeType == XmlNodeType.EndElement )
							return;
						break;
					case "DesignerControl":
						if ( reader.NodeType == XmlNodeType.Element ) {
							string typename = reader.GetAttribute("Type");
							DesignerControl dc = AddSerializedDesignerControl(typename, reader);
							if ( dc is IFSymbol ) {
								_ifSymbols.Add((IFSymbol)dc);
								dc.SizeChanged += new EventHandler(ifsymbol_SizeChanged);
							}
						}
						break;
				}
			}
		}
		private void readTHENELSE(XmlReader reader)
		{
			while ( reader.Read() ) {
				switch ( reader.Name ) {
					case "THENELSE":
						if ( reader.NodeType == XmlNodeType.EndElement )
							return;
						break;
					case "DesignerControl":
						if ( reader.NodeType == XmlNodeType.Element ) {
							string typename = reader.GetAttribute("Type");
							DesignerControl dc = AddSerializedDesignerControl(typename, reader);
							if ( dc is THENELSESymbol ) {
								_thenelseSymbol = (THENELSESymbol)dc;
								_thenelseSymbol.Anchor = System.Windows.Forms.AnchorStyles.Top |
														 System.Windows.Forms.AnchorStyles.Right |
														 System.Windows.Forms.AnchorStyles.Bottom;
							}
						}
						break;
				}
			}
		}
		private void readTHEN(XmlReader reader)
		{
			while ( reader.Read() ) {
				switch ( reader.Name ) {
					case "THEN":
						if ( reader.NodeType == XmlNodeType.EndElement )
							return;
						break;
					case "DesignerControl":
						if ( reader.NodeType == XmlNodeType.Element ) {
							string typename = reader.GetAttribute("Type");
							DesignerControl dc = AddSerializedDesignerControl(typename, reader);
							if ( dc is THENResultSymbol ) {
								THENResultSymbol thenSymbol = (THENResultSymbol)dc;
								thenSymbol.Anchor = System.Windows.Forms.AnchorStyles.Top |
														 System.Windows.Forms.AnchorStyles.Right;
								thenSymbol.SizeChanged += new EventHandler(this.thenelsesymbol_SizeChanged);
								_thenSymbols.Add(thenSymbol);
							}
						}
						break;
				}
			}
		}
		private void readELSE(XmlReader reader)
		{
			while ( reader.Read() ) {
				switch ( reader.Name ) {
					case "ELSE":
						if ( reader.NodeType == XmlNodeType.EndElement )
							return;
						break;
					case "DesignerControl":
						if ( reader.NodeType == XmlNodeType.Element ) {
							string typename = reader.GetAttribute("Type");
							DesignerControl dc = AddSerializedDesignerControl(typename, reader);
							if ( dc is ELSEResultSymbol ) {
								_elseSymbol = (ELSEResultSymbol)dc;
								_elseSymbol.Anchor = System.Windows.Forms.AnchorStyles.Top |
														 System.Windows.Forms.AnchorStyles.Right;
								_elseSymbol.SizeChanged += new EventHandler(this.thenelsesymbol_SizeChanged);
							}
						}
						break;
				}
			}
		}
		private void readONERROR(XmlReader reader)
		{
			while ( reader.Read() ) {
				switch ( reader.Name ) {
					case "ONERROR":
						if ( reader.NodeType == XmlNodeType.EndElement )
							return;
						break;
					case "DesignerControl":
						if ( reader.NodeType == XmlNodeType.Element ) {
							string typename = reader.GetAttribute("Type");
							DesignerControl dc = AddSerializedDesignerControl(typename, reader);
							if ( dc is ONERRORResultSymbol ) {
								_onerrorSymbol = (ONERRORResultSymbol)dc;
								_onerrorSymbol.Anchor = System.Windows.Forms.AnchorStyles.Top |
														 System.Windows.Forms.AnchorStyles.Right;
								_onerrorSymbol.SizeChanged += new EventHandler(this.thenelsesymbol_SizeChanged);
							}
						}
						break;
				}
			}
		}

		public override void WriteXml(XmlWriter writer)
		{
			System.ComponentModel.BooleanConverter bc = new System.ComponentModel.BooleanConverter();
			WriteStandardProperties(writer);

			// Start IF
			writer.WriteStartElement("IF");
			foreach ( IFSymbol ifsymbol in _ifSymbols ) {
				writer.WriteStartElement("DesignerControl");
				ifsymbol.WriteXml(writer);
				writer.WriteEndElement();
			}
			writer.WriteEndElement();
			// End IF

			if ( _thenelseSymbol != null ) {
				// Start ELSE
				writer.WriteStartElement("THENELSE");
				writer.WriteStartElement("DesignerControl");
				_thenelseSymbol.WriteXml(writer);
				writer.WriteEndElement();
				writer.WriteEndElement();
				// End ELSE
			}

			if ( _thenSymbols.Count > 0 ) {
				// Start THEN
				writer.WriteStartElement("THEN");
				foreach ( THENResultSymbol thensymbol in _thenSymbols ) {
					writer.WriteStartElement("DesignerControl");
					thensymbol.WriteXml(writer);
					writer.WriteEndElement();
				}
				writer.WriteEndElement();
				// End THEN
			}

			if ( _elseSymbol != null ) {
				// Start ELSE
				writer.WriteStartElement("ELSE");
				writer.WriteStartElement("DesignerControl");
				_elseSymbol.WriteXml(writer);
				writer.WriteEndElement();
				writer.WriteEndElement();
				// End ELSE
			}

			if ( _onerrorSymbol != null ) {
				// Start ONERROR
				writer.WriteStartElement("ONERROR");
				writer.WriteStartElement("DesignerControl");
				_onerrorSymbol.WriteXml(writer);
				writer.WriteEndElement();
				writer.WriteEndElement();
				// End ONERROR
			}
			// add business rule informations
			if ( _brule != null ) {
				writer.WriteStartElement("RepositoryBusinessRule");
				writer.WriteAttributeString("id", _brule.ID.ToString());
				writer.WriteAttributeString("name", _brule.Name);
				if ( this.DesignerViewControl.MainControl == this )
					writer.WriteAttributeString("isMainControl", true.ToString());
				else
					writer.WriteAttributeString("isMainControl", false.ToString());
				writer.WriteAttributeString("isRef", bc.ConvertToString(this.IsReference));
				writer.WriteEndElement();
			}

			// add only AND / OR symbols to the DesignerControls list
			writer.WriteStartElement("DesignerControls");
			foreach ( DesignerControl dc in this.Controls ) {
				if ( dc is ANDSymbol || dc is ORSymbol ) {
					writer.WriteStartElement("DesignerControl");
					dc.WriteXml(writer);
					writer.WriteEndElement();
				}
			}
			foreach ( DesignerControl dc in this.DesignerViewControl.DesignerControls.Routes ) {
				Route r = dc as Route;
				if ( this.Controls.Contains(r.StartControl) || this.Controls.Contains(r.EndControl) ) {
					writer.WriteStartElement("Route");
					dc.WriteXml(writer);
					writer.WriteEndElement();
				}
			}
			writer.WriteEndElement();
		}

		#endregion

		#region IRepositoryItemSymbol Members

		public bool SaveHierarchy
		{
			get { return true; }
		}

		private bool _isReference = false;
		public bool IsReference
		{
			get { return _isReference; }
			set { _isReference = value; }
		}

		public bool CanBeMainControl
		{
			get { return false; }
		}
		private Repository.RepositoryBusinessRule _brule;
		public OpenComposite.EII.Repository.IRepositoryItem RepositoryItem
		{
			get { return _brule; }
			set
			{
				if ( (IRepositoryItem)_brule != value ) {
					_brule = value as Repository.RepositoryBusinessRule;
					doBRuleChanged();
				}
			}
		}

		private void doBRuleChanged()
		{
			if ( _brule != null ) {
				this.Text = _brule.Name;
				BusinessPolicy policy = _brule.GetPolicy();
				if ( policy != null && policy.NText == BusinessPolicy.cParticipantPolicy ) {
					this.BeginUpdate();
					_imgUser = Resources.png_user;
					_isParticipantRule = true;
					this.NameTextBox.Left += ( _imgUser.Width + 5 );
					this.NameTextBox.Width -= ( _imgUser.Width + 5 );
					this.EndUpdate();
				} else {
					_imgUser = null;
					_isParticipantRule = false;
				}
				initIFTHENELSESymbols();
			}
		}

		public void Load(int idRepository, int idDomain)
		{
			if ( _brule == null || _brule.IsDeleted ) {
				// Remove Business Rule Symbol
				this.Remove();
			} else {
				//BusinessPolicy policy = _brule.GetPolicy();
				//if ( policy != null && policy.NText == BusinessPolicy.cParticipantPolicy ) {
				//    this.BeginUpdate();
				//    _imgUser = Resources.png_user;
				//    _isParticipantRule = true;
				//    this.NameTextBox.Left += ( _imgUser.Width + 5 );
				//    this.NameTextBox.Width -= ( _imgUser.Width + 5 );
				//    this.EndUpdate();
				//} else {
				//    _imgUser = null;
				//    _isParticipantRule = false;
				//}
			}
		}

		public bool Save(int idRepository, int idDomain)
		{
			List<int> nouns = new List<int>();
			foreach ( IFSymbol ifs in this.IfList ) {
				int leftNoun = ifs.IFCondition.LeftNounID;
				int rightNoun = ifs.IFCondition.RightNounID;
				if ( leftNoun > 0 && !nouns.Contains(leftNoun) ) {
					nouns.Add(ifs.IFCondition.LeftNounID);
				}
				if ( rightNoun > 0 && !nouns.Contains(rightNoun) ) {
					nouns.Add(ifs.IFCondition.RightNounID);
				}
				DesignerControl[] preds = ifs.GetPredecessors();
				if ( preds != null ) {
					foreach ( DesignerControl pred in preds ) {
						if ( pred.Parent != null && pred.Parent.Parent != null &&
							 pred.Parent.Parent is BusinessRuleSymbol )
							( (BusinessRuleSymbol)pred.Parent.Parent ).Save(idRepository, idDomain);
					}
				}
			}
			//List<string> vocabulary;
			//List<string> rulenames;
			//string code = BusinessRulesCodeGenerator.GenerateBusinessRuleCode(this,
			//    out vocabulary, out rulenames);

			//List<string> vocabWF;
			//List<string> rulesWF;
			Dictionary<string, string> parameters;
			List<string> results;
			List<int> bruleIDs;
			List<int> ruleConstIDs;
			string codeWF = BusinessRulesCodeGenerator.GenerateOrchestrationRuleCode(this,
				out parameters, out results, out bruleIDs, out ruleConstIDs);

			if ( _brule == null ) {
				_brule = new OpenComposite.EII.Repository.RepositoryBusinessRule(true);
			}
			#region Obsolete
			//if ( _brule != null && _brule.BusinessRule == null ) {
			//    //_brule.BusinessRule = new OpenComposite.Base.BusinessRule();
			//}
			#endregion
			_brule.Name = this.Text;
			_brule.RuleCode = codeWF;
			_brule.SetParameters(parameters);
			_brule.SetUsedBusinessRuleIDs(bruleIDs);
			_brule.Results = string.Join(";", results.ToArray());
			_brule.SetUsedNounIDs(nouns);
			_brule.SetUsedRuleConstantIDs(ruleConstIDs);
			if ( this.IsParticipantRule ) {
				_brule.ExtendedProperties.RuleType = RepositoryBusinessRule.BusinessRuleType.ParticipantRule;
			} else {
				_brule.ExtendedProperties.RuleType = RepositoryBusinessRule.BusinessRuleType.GenericRule;
			}
			_brule.ExtendedProperties.Conditions.Clear();
			foreach ( var item in this.IfList ) {
				_brule.ExtendedProperties.Conditions.Add(item.IFCondition);
			}
			//_brule.BusinessRule.Display = this.Text;
			//_brule.BusinessRule.Text = this.Text;
			//_brule.BusinessRule.Formula = code;
			//_brule.BusinessRule.ParentRule = "GeneratedRules";
			//_brule.BusinessRule.RuleType = "0";
			//_brule.BusinessRule.CodeType = "csharp";
			//_brule.BusinessRule.Type = "Rule";

			this.SaveToXmlDiagram();
			_brule.Save();

			// add vocabulary to enterprise variables and to process business rule
			//Global.BusinessRuleData.DeleteRuleVariables(_brule.BusinessRuleName, Global.CurrentUser.OrganizationID);
			//if ( vocabulary != null && vocabulary.Count > 0 ) {
			//    foreach ( string var in vocabulary ) {
			//        Global.BusinessRuleData.InsertVariable(var, "", Global.CurrentUser.OrganizationID,
			//            "Variable", "Generated", "string");
			//        Global.BusinessRuleData.InsertRuleVariable(_brule.BusinessRuleName, var,
			//            Global.CurrentUser.OrganizationID);
			//    }
			//}
			// TODO: Save vocabulary of referenced rules


			return true;
		}

		public bool Delete(bool bAsk)
		{
			if ( _isInRepositoryDelete ) return true;
			_isInRepositoryDelete = true;
			bool ok = true;
			try {
				if ( _brule != null ) {
					ok = _brule.Delete(bAsk);
				}
				if ( ok ) {
					this.Remove();
				}
			} finally {
				_isInRepositoryDelete = false;
			}
			return ok;
		}

		#endregion
	}
}
